#include <Uefi.h>
#include <Base.h>
#include <IndustryStandard/Acpi.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/IoLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
#include "AcpiApp.h"

UINT8   *gRSDPPointer  = NULL;
UINT8   *gRSDTPointer  = NULL;
UINT8   *gXRSDTPointer = NULL;

UINT8   SignatureSrt[5] = {0};

UINT8 *
GetRSDPPointer () 
{
  UINT32  Index = 0;
  UINT64  Data = 0;

  Data = MmioRead64 (ACPI_BEGIN_ADDRESS + Index);
  while ((Data != ACPI_RSDP_SIGNATURE) && ((ACPI_BEGIN_ADDRESS + Index) < ACPI_END_ADDRESS)) {
    Index++;
    Data = MmioRead64 (ACPI_BEGIN_ADDRESS + Index);
  }

  if ((ACPI_BEGIN_ADDRESS + Index) == ACPI_END_ADDRESS) {
    Print (L"Search RSDP error\n");
    return NULL;
  }

  return (UINT8 *)(UINT64)(ACPI_BEGIN_ADDRESS + Index);
}


EFI_STATUS
GetXRSDTPointer (
  OUT UINT8 **RSDTPointer,
  OUT UINT8 **XRSDTPointer
  )
{
  EFI_STATUS  Status = EFI_SUCCESS;
  EFI_ACPI_6_5_ROOT_SYSTEM_DESCRIPTION_POINTER  *RSDPEntry = NULL;

  RSDPEntry = (EFI_ACPI_6_5_ROOT_SYSTEM_DESCRIPTION_POINTER *)gRSDPPointer;

  if ((RSDPEntry->RsdtAddress == 0) && (RSDPEntry->XsdtAddress == 0)) {
    Status = EFI_NOT_FOUND;
  }


  if (RSDPEntry->RsdtAddress == 0) {
    *RSDTPointer = NULL;
  } else {
    Print (L"Get RsdtAddress\n");
    *RSDTPointer = (UINT8 *)(UINT64)(RSDPEntry->RsdtAddress);
  }

  if (RSDPEntry->XsdtAddress == 0) {
    *XRSDTPointer = NULL;
  } else {
    Print (L"Get XsdtAddress\n");
    *XRSDTPointer = (UINT8 *)(UINT64)(RSDPEntry->XsdtAddress);
  }
  
  return Status;
}

VOID
ListOtherTalbeByRSDT ()
{
  UINT32 Signature  = 0;
  UINT32 Length     = 0;
  UINT16 EntryIndex = 0; 

  Signature = *(UINT32 *)gRSDTPointer;
  if (Signature != ACPI_RSDT_SIGNATURE) {
    Print (L"Signature != ACPI_RSDT_SIGNATURE\n");
    return;
  }

  Print (L"RSDT: \n");

  Length = *(UINT32 *)(gRSDTPointer + 4);
  Length = Length - 0x24;
  while ((EntryIndex < Length) && ((Length - EntryIndex) >= 4)) {
    Signature = *(UINT32 *)((UINT64)(*(UINT32 *)(gRSDTPointer + 0x24 + EntryIndex)));
    CopyMem (SignatureSrt, &Signature, 4);
    Print (L" %a : 0x%lx\n", SignatureSrt, *(UINT32 *)(gRSDTPointer + 0x24 + EntryIndex));
    EntryIndex = EntryIndex + 4;
  }

}

VOID
ListOtherTalbeByXSDT ()
{
  UINT32 Signature = 0;
  UINT32 Length     = 0;
  UINT16 EntryIndex = 0; 

  Signature = *(UINT32 *)gXRSDTPointer;
  if (Signature != ACPI_XSDT_SIGNATURE) {
    Print (L"Signature != ACPI_XSDT_SIGNATURE\n");
    return;
  }

  Print (L"XSDT: \n");

  Length = *(UINT32 *)(gXRSDTPointer + 4);
  Length = Length - 0x24;
  while ((EntryIndex < Length) && ((Length - EntryIndex) >= 8)) {
    Signature = *(UINT32 *)((UINT64)(*(UINT64 *)(gXRSDTPointer + 0x24 + EntryIndex)));
    CopyMem (SignatureSrt, &Signature, 4);
    Print (L" %a : 0x%llx\n", SignatureSrt, *(UINT64 *)(gXRSDTPointer + 0x24 + EntryIndex));
    EntryIndex = EntryIndex + 8;
  }

}